var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
// TypeScript 是面向对象的 JavaScript。
// 类描述了所创建的对象共同的属性和方法。
// TypeScript 支持面向对象的所有特性，比如 类、接口等。
var Person = /** @class */ (function () {
    function Person(name) {
        this.name = name;
    }
    Person.prototype.eat = function () {
        console.log("吃东西");
    };
    return Person;
}());
// 创建实例对象
var coder = new Person("张三");
// 访问属性或者方法
coder.eat();
// 类的继承
// TypeScript 支持继承类，即我们可以在创建类的时候继承一个已存在的类，这个已存在的类称为父类，继承它的类称为子类。
// 类继承使用关键字 extends，子类除了不能继承父类的私有成员(方法和属性)和构造函数，其他的都可以继承。
// TypeScript 一次只能继承一个类，不支持继承多个类，但 TypeScript 支持多重继承（A 继承 B，B 继承 C）。
var Root = /** @class */ (function () {
    function Root() {
    }
    return Root;
}());
var Child = /** @class */ (function (_super) {
    __extends(Child, _super);
    function Child() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return Child;
}(Root));
var Leaf = /** @class */ (function (_super) {
    __extends(Leaf, _super);
    function Leaf() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return Leaf;
}(Child)); // 多重继承，继承了 Child 和 Root 类
var obj = new Leaf();
obj.str = "hello";
console.log(obj.str);
// 继承类的方法重写
// 类继承后，子类可以对父类的方法重新定义，这个过程称之为方法的重写。
// 其中 super 关键字是对父类的直接引用，该关键字可以引用父类的属性和方法。
var Person1 = /** @class */ (function () {
    function Person1(name) {
        this.name = name;
    }
    Person1.prototype.sayHello = function () {
        console.log("person1 hello");
    };
    return Person1;
}());
var Person2 = /** @class */ (function (_super) {
    __extends(Person2, _super);
    function Person2() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Person2.prototype.sayHello = function () {
        _super.prototype.sayHello.call(this);
        console.log("Person2 say hello");
    };
    return Person2;
}(Person1));
var p2 = new Person2("p2");
p2.sayHello();
// static
// static 关键字用于定义类的数据成员（属性和方法）为静态的，静态成员可以直接通过类名调用。
var staticCalss = /** @class */ (function () {
    function staticCalss() {
    }
    var _a;
    _a = staticCalss;
    staticCalss.staticName = "staticName";
    staticCalss.syaStaticName = function () {
        console.log("sya" + _a.staticName);
    };
    return staticCalss;
}());
staticCalss.syaStaticName();
// instanceof 使用和js相同 判断对象是否属于某个指定类型
var TestIntanceOf = /** @class */ (function () {
    function TestIntanceOf() {
    }
    return TestIntanceOf;
}());
var testIntanceOf = new TestIntanceOf();
console.log(testIntanceOf instanceof TestIntanceOf);
// 访问控制修饰符，由于属性能被任意修改，因此需要限制
// TypeScript 中，可以使用访问控制符来保护对类、变量、方法和构造方法的访问。TypeScript 支持 3 种不同的访问权限。
// public（默认） : 公有，可以在任何地方被访问。
// protected : 受保护，可以被其自身以及其子类访问。
// private : 私有，只能被其定义所在的类访问。
// 可以通过方法将私有方法暴露在实力中方法
var TestP = /** @class */ (function () {
    function TestP(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    TestP.prototype.getSex = function () {
        return this.sex;
    };
    TestP.prototype.getAge = function () {
        return this.age;
    };
    TestP.prototype.setAge = function (age) {
        // 判断年龄是否合法
        if (age > 0) {
            this.age = age;
        }
    };
    return TestP;
}());
var ChildTest = /** @class */ (function (_super) {
    __extends(ChildTest, _super);
    function ChildTest() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ChildTest.prototype.getParentSex = function () {
        return this.age;
    };
    return ChildTest;
}(TestP));
var testp = new TestP("李四", 19, "男");
console.log(testp.name);
// console.log(testp.age);
// console.log(testp.sex); Property 'sex' is private and only accessible within class 'TestP'.
console.log(testp.getAge());
console.log(testp.getSex());
testp.setAge(20);
console.log(testp.getAge());
testp.setAge(-20);
console.log(testp.getAge());
var chil = new ChildTest("张三", 19, "女");
console.log(chil.getParentSex());
var TestStr = /** @class */ (function () {
    function TestStr(str) {
        this.str = str;
    }
    TestStr.prototype.sayStr = function () {
        console.log(this.str);
    };
    return TestStr;
}());
var testStr = new TestStr("hrllo str");
testStr.sayStr();
// 抽象类 专门用来被继承的类，不能实例化
var Animal = /** @class */ (function () {
    function Animal(name) {
        this.name = name;
    }
    return Animal;
}());
var Cat = /** @class */ (function (_super) {
    __extends(Cat, _super);
    function Cat() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Cat.prototype.sayHello = function () {
        console.log("喵喵喵~~");
    };
    return Cat;
}(Animal));
// 接口和抽象类的区别
// 1、关键字不同
// 2、抽象类中可以有抽象方法，可以有普通方法，抽象方法必须继承实现，但是接口中都是抽象方法，必须实现
// 3、接口主要定义一种标准，限制类来实现接口
// 泛型---在定义类和函数时候，如果遇到类型不明确就可以使用
//  普通方法
function ft(a) {
    return 1;
}
function fn(a) {
    return a;
}
// 可以直接调用具有泛型的函数
var a = fn(10); // 不指定泛型，js可以对类型自动进行推断
console.log("a", a);
console.log(fn("hello"));
